home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
cpp_libs
/
tools
/
classdoc.lha
/
classdoc
/
classdoc.awk
< prev
next >
Wrap
Text File
|
1993-08-08
|
6KB
|
286 lines
# classdoc.awk
#
# This awk script tries to produce a manual page from a C++ header file.
# The idea is to make the documentation more readable, without maintaining
# a separate file. Typical usage:
#
# gawk -f classdoc.awk list.H | nroff -man
#
# Although the result may not be exactly as intended, nothing in the file
# (except #if, #ifdef, #ifndef, #endif) is supposed to be thrown away.
# Major problem: comments associated with stuff that is saved (typedef, #define,
# etc.), is not saved but appears with some unrelated code.
# Improvemnts are gratefully accepted.
#
# Author: Dag Michael Bruck, Department of Automatic Control, Lund Institute
# of Technology, Box 118, S-221 00 Lund, SWEDEN. E-mail: dag@control.lth.se
#
# Version: 2.5 Last change: 1990-05-15
#
FNR == 1 {
"ls -l " FILENAME | getline Date;
Date = substr(Date, 33, 12);
print ".TH",FILENAME,"C++","\""Date"\"","\"ClassDoc 2.5\"","\\&";
Section = "None";
SubSect = "None";
ContinueStat = 0;
}
#
# Stop class ducumentation
#
/CLASSDOC[ \t]+OFF/ {
while ($0 !~ /CLASSDOC[ \t]+ON/)
getline;
getline;
}
#
# #define macro, placed at end of manual page
#
$1 == "#define" {
$0 = dropfirst($0);
match($0, /[A-Za-z0-9_]+(\([^\)]*\))?/);
save("define", substr($0, RSTART, RLENGTH));
eatcontinuation();
next;
}
#
# #include files, placed at end
#
$1 == "#include" {
save("include", substr($2, 2, length($2)-2));
next;
}
#
# Drop some cpp directives
#
$1 == "#if" { next; }
$1 == "#ifdef" { next; }
$1 == "#ifndef" { next; }
$1 == "#else" { next; }
$1 == "#elif" { next; }
$1 == "#endif" { next; }
#
# Extrnal declarations, placed at end
#
$1 == "extern" {
save("extern", dropfirst($0));
next;
}
#
# Typedef declaration, placed at end
#
$1 == "typedef" {
save("typedef", dropfirst($0));
next;
}
#
# Class declarations, place at end
#
$1 ~ /^class$|^struct$/ && $2 ~ /;$/ {
save("classdecl", $1 " " substr($2, 1, length($2)-1));
next;
}
#
# C++ comment (the /* ... */ variant is not recognized)
#
$1 ~ /^\/\// {
if (!(Section ~ /Description|Class|Code/))
section("Description", "DESCRIPTION");
if (InComment == 0) {
if (Section == "Description")
print ".fi\n.ft R\n.PP";
else
print ".fi\n.ft R\n.sp 0.1v\n.RS 0.25i";
};
if (NF == 1)
print ".PP";
else {
match($0, /\/\/[ ]*/);
print substr($0, RSTART+RLENGTH);
}
InComment = 1;
next;
}
#
# Class definition
#
$1 ~ /^class$/ && Section != "Class" {
section("Class", "CLASS " $2);
if (NF > 4) {
subsect("Base", "Base class");
print ".fi\n.ft R";
for (i=4; i < NF; i++)
print $i;
print ".nf\n.ft B";
};
next;
}
#
# Struct definition - almost a class
#
$1 ~ /^struct$/ && Section != "Class" {
section("Class", "STRUCT " $2);
subsect("Public", "Public members");
next;
}
#
# End of class definition
#
$1 == "};" {
Section = "None";
SubSect = "None";
InComment = 0;
next;
}
#
# Friend declaration, only in classes
#
$1 == "friend" {
subsect("Friend", "Friends");
print dropfirst($0);
next;
}
#
# Public, protected and private parts of a class
#
/public:/ {
subsect("Public", "Public members");
next;
}
/protected:/ {
subsect("Protected", "Protected members");
next;
}
/private:/ {
subsect("Private", "Private members");
next;
}
#
# Everything else inside a class (not comments)
#
Section == "Class" {
if (InComment == 1)
print ".RE\n.PP\n.nf\n.ft B";
if (NF > 0) print substr($0, index($0, $1));
if (match($0, /,[ \t]*$/)) {
if (ContinueStat == 0) print ".RS 1i\n.ft B";
ContinueStat = 1;
}
else if (ContinueStat == 1) {
print ".RE\n.ft B";
ContinueStat = 0;
}
InComment = 0;
next;
}
#
# Blank lines
#
NF == 0 {
print ".PP"
if (Section == "Code")
print ".nf\n.ft B";
next;
}
#
# Everything else (outside classes)
#
{
if (Section != "Code")
section("Code", "CODE");
if (InComment == 1) {
print ".RE\n.PP\n.nf\n.ft B";
InComment = 0;
};
print;
next;
}
#
# Post-processing: list class declarations, external declarations,
# macro definitions and includec files.
#
END {
if (issaved("classdecl")) {
print ".SH CLASS DECLARATIONS\n.nf";
printsaved("classdecl");
}
if (issaved("extern")) {
print ".SH EXTERNAL DECLARATIONS\n.nf";
printsaved("extern");
}
if (issaved("typedef")) {
print ".SH TYPE DEFINITIONS\n.nf";
printsaved("typedef");
}
if (issaved("define")) {
print ".SH DEFINED MACROS\n.nf";
printsaved("define");
}
if (issaved("include")) {
print ".SH INCLUDED FILES\n.nf";
printsaved("include");
}
}
#
# dropfirst(str) - returns string without its first field
#
function dropfirst(str)
{
if (match(str, /^[ \t]*[^ \t]*[ \t]+/))
return substr(str, RLENGTH+1);
else
return str;
}
#
# save, ... - functions for saving text in an area, printing it, etc.
#
function save(area, str)
{
TextCount[area]++;
TextArea[area, TextCount[area]] = str;
}
function issaved(area)
{
return TextCount[area] > 0;
}
function printsaved(area, i)
{
for (i = 1; i <= TextCount[area]; i++)
print TextArea[area, i];
}
#
# section(sect, heading) - change section, no subsection
#
function section(sect, heading)
{
if (sect != Section) {
Section = sect;
print ".SH", heading;
print ".nf\n.ft B";
InComment = 0;
}
SubSect = "None";
}
#
# subsect(subs, heading) - change subsection
#
function subsect(subs, heading)
{
if (subs != SubSect) {
SubSect = subs;
print ".SS", heading;
print ".nf\n.ft B";
InComment = 0;
}
}
#
# eatcontinuation() - eat continuation lines (preceding line ended in \)
#
function eatcontinuation()
{
while ($0 ~ /\\$/)
getline;
}